home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************
- * *
- * Minimal Term for DNET (uc) Stone, SST *
- * Further modifications by Unknown, SST *
- * Based on FTerm by Matt Dillon *
-
- Opens a terminal inside a CLI (for use with WSHELL
- or SPHINX)
-
- * *
- * ShellTerm [DNET_PORT] [NETWORK] *
- * *
- * Set ya TABS to 4! *
- * Email me!! c9107253@mystra.newcastle.edu.au *
- * For any reason!! (eg DNet, AmiNet, Demos, amigas...) *
- * Please send any changes U make! *
- * Fully public domain *
- * Mega-thanx to Azza of the SST for hours of DNET source *
- * modification.... yes it compiles under SAS 6! *
- * *
-
- BUGS:
- the way the conwindow size is determined is not
- fail safe... so programs such a vi only sometimes work
- readjust the window smaller if this happens
-
- toggling between raw and buffer modes may take up to
- 1/2 second this can be fixed if 2 file locks on the
- input are used.
-
- Any others?
-
- * *
- **********************************************************/
-
- #include "defs.h"
-
- /* DEFAULT STRINGS */
- char *WHITE = " \n\r\t",
- *EOLN = "\n\r";
-
- /* STANDARD FILE HANDLES */
- long out, err, in;
-
- /* WINDOW SIZE */
- short columns = 0, rows = 0;
-
- /* FILE HANDLES */
- struct AFileHandle *ain, *aout, *alogfile;
-
- /* PROGRAM FLAGS */
- char overridepkt, prevmoderaw, rawlocalecho, moderaw, notdone, gettingoptions,
- checkwindowsize;
- long lineend;
-
- char Buf[512], prg[40], logfilename[100];
- void *chan;
- long startmem;
-
- /* Window pointer of the console window (if we are interactive) */
- struct Window *conwdw;
- #define COLUMNS(a) ((a)->GZZWidth / (((a)->IFont->tf_XSize>0) ? (a)->IFont->tf_XSize:1))
- #define ROWS(a) ((a)->GZZHeight / (((a)->IFont->tf_YSize>0) ? (a)->IFont->tf_YSize:1))
-
- extern struct IntuitionBase *IntuitionBase;
- extern struct GfxBase *GfxBase;
-
-
- #define SIGNALS (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F)
-
- /* standard in & out async file handles */
- #define INBUFSIZE 500
- #define WAIT_TIMEOUT 700000 /* uSeconds */
-
-
- /* Do this on the next packet return */
- #define IN_NULL 0
- #define IN_WAIT 1
- #define IN_CHARS 2
- #define IN_RAWSET 3
- #define IN_RAWCLR 4
-
-
- /**********************************************************/
- void DoPacket(struct AFileHandle *afh, void *qbuf,
- long size, char pkttype)
- /**********************************************************
- Send a packet according to type. qbuf & size may not
- be required (in fact only used for ARead)
- **********************************************************/
- {
- switch(pkttype) {
- case IN_WAIT:
- ASendPacket(afh, ACTION_WAIT_CHAR, WAIT_TIMEOUT, 0, 0, 0); break;
- case IN_CHARS:
- ARead(afh, qbuf, size); break;
- case IN_RAWSET:
- ASendPacket(afh, ACTION_SCREEN_MODE, 1, 0, 0, 0); break;
- case IN_RAWCLR:
- ASendPacket(afh, ACTION_SCREEN_MODE, 0, 0, 0, 0); break;
- }
- }
-
-
-
- /* pass: rest of argline, command table, command count*4 */
- typedef void *(* cmdfunc)(char *);
- /**********************************************************
- Commands available
- **********************************************************/
-
- /* NOTE!!! ARGUMENTS **MUST** FIT PROTOTYPE of cmdfunc!!!! */
-
- void cmds_raw(void)
- { overridepkt = IN_RAWSET; }
- void cmds_buf(void)
- { overridepkt = IN_RAWCLR; }
- void cmds_lf(void)
- { lineend = 0x0a000000; }
- void cmds_cr(void)
- { lineend = 0x0d000000; }
- void cmds_lfcr(void)
- { lineend = 0x0a0d0000; }
- void cmds_send(char *rest)
- { long n; if(rest && (n = strlen(rest))) DWrite(chan, rest, n); }
- void cmds_flush(void)
- { DIoctl(chan, CIO_FLUSH, 0, 0); fpf(err,"\nFlushed\n"); }
- void cmds_closelog(void)
- {
- if(!alogfile) return;
- fpf(err,"'%s' ", logfilename);
- ASafeClose(&alogfile);
- fpf(err,"closed ok.\n");
- }
- void cmds_log(char *rest)
- {
- cmds_closelog();
- if(!rest) return;
- spf(logfilename, sizeof(logfilename), rest, aout);
- fpf(err,"'%s' ", logfilename);
- if( !(alogfile = AEasyOpen(aout, rest, MODE_NEWFILE)) )
- fpf(err,"failed.\n"); else fpf(err,"opened ok.\n");
- }
- void cmds_execute(char *rest)
- {
- if(!rest) return;
- fpf(err,"%s Executing '%s'\n", prg, rest);
- Execute(rest, NULL, err);
- fpf(err,"%s Terminating '%s'\n", prg, rest);
- }
- void cmds_localecho(void)
- { rawlocalecho = 1; }
-
- void cmds_localechooff(void)
- { rawlocalecho = 0; }
-
- void cmds_ctrlf(void)
- { char c = 6; DWrite(chan, &c, 1); }
-
- void cmds_quit(void)
- { notdone = 0; }
-
- void cmds_getoptions(void)
- {
- fpf(err,"\n%s (%ld x %ld) ? <return> for help\n", prg, columns, rows);
- if(prevmoderaw = moderaw) overridepkt = IN_RAWCLR;
- gettingoptions = 1;
-
- }
- /** ADD ANY NEW COMMANDS HERE */
-
-
- #define NOOFCMDS ((sizeof(cmds)/4)/4)
- void cmds_help(char *dummy);
- static char *cmds[] = {
- "HELP","?","This message", (char *)cmds_help,
- "RAW","R","Raw (normal terminal) mode", (char *)cmds_raw,
- "BUF","B","Line buffered (shell) mode", (char *)cmds_buf,
- "LFCR",NULL,"Linefeed & Carriage Return",(char *)cmds_lfcr,
- NULL,"LF","Linefeed", (char *)cmds_lf,
- NULL,"CR","Carriage return", (char *)cmds_cr,
- "SEND",NULL,"Send text", (char *)cmds_send,
- "FLUSH","^F","Flush input", (char *)cmds_flush,
- "EXECUTE","X","AmigaDOS command", (char *)cmds_execute,
- "LOCALECHO","LE","Raw mode local echo on",(char *)cmds_localecho,
- "LOCALECHOOFF","LEO","Raw mode local echo off",(char *)cmds_localechooff,
- "LOG","L","Log to file", (char *)cmds_log,
- "CLOSELOG","CL","Close log file", (char *)cmds_closelog,
- NULL,"F","Send CTRL-F", (char *)cmds_ctrlf,
- "QUIT", NULL, "Quit terminal", (char *)cmds_quit
- };
-
- void cmds_help(char *dummy)
- { short j, i;
- fpf(err,"Known commands:\n");
- for(j = 0, i = 0; i < NOOFCMDS; j += 4, i++ )
- if(cmds[j+1] && cmds[j])
- fpf(err, "%s\tor %s (%s)\n",cmds[j+1], cmds[j], cmds[j+2]);
- else if(cmds[j+1])
- fpf(err, "%s\t(%s)\n", cmds[j+1], cmds[j+2]);
- else if(cmds[j])
- fpf(err, "%s\t(%s)\n", cmds[j], cmds[j+2]);
- }
- /**********************************************************/
- void *ParseCommand(char *cmd)
- /**********************************************************
- Send this routine a command string and it will try and
- do something with it!
- **********************************************************/
- {
- char cmdbuf[400], *command, *rest;
- short n;
-
- /** KICK BACK INTO RAW IF WE WERE BEFORE (THO THIS MAY CHANGE) */
- overridepkt = prevmoderaw? IN_RAWSET : IN_NULL;
-
- /** GET THE COMMAND */
- CopyMem(cmd, cmdbuf, sizeof(cmdbuf)-1); cmdbuf[sizeof(cmdbuf)-1] = 0;
- command = SkipChar(cmdbuf, WHITE);
- if(!command) return(NULL);
- if( rest = FindChar(command, WHITE)) {
- char *temp = SkipChar(rest, WHITE);
- rest[0] = '\0'; rest = temp;
- if(rest) {
- temp = FindChar(rest, EOLN);
- if(temp) temp[0] = '\0';
- }
- }
- strupper(command);
-
- /** DETERMINE THE COMMAND & DO THE CALL! */
- if((n = CmpString(command, cmds, NOOFCMDS, 4)) == -1 )
- if((n = CmpString(command, &cmds[1], NOOFCMDS, 4)) == -1 )
- { fpf(err, "%s unrecognised\n", command); return(NULL); }
- /* fpf(err, "%s corresponds to %ld\n", command, n); */
- return(((cmdfunc)cmds[(n<<2)+3])(rest));
- }
-
-
-
-
- typedef short (* mapfunc)(void *, char);
- /**********************************************************/
- long MapText(mapfunc fn, void *fn_data,
- unsigned char buffer[], short n)
- /**********************************************************
- Bit of a mess... just map some characters to others...
- **********************************************************/
- {
- short i,j;
- long w;
- char *eoln;
- eoln = (char *)&lineend;
- for(w = 0, i = 0; i < n; i++) {
- switch(buffer[i]) {
- case 0x03: /** CTRL-C */
- case 0x04: /** CTRL-D */
- case 0x05: /** CTRL-E */
- case 0x06: /** CTRL-F */
- break;
-
- case 0x0a:
- case 0x0d: /** RETURN */
- for(j = 0; eoln[j]; j++)
- if(!fn(fn_data, eoln[j])) return(w); else w++;
- break;
- case 0x9b: /** ARROW KEY ESCAPE */
- if(!fn(fn_data, 0x1b)) return(w); else w++;
- if(!fn(fn_data, '[')) return(w); else w++;
- break;
-
- default: /** PUT THROUGH */
- if(!fn(fn_data, buffer[i])) return(w); else w++;
- }
- }
- return(w);
- }
-
- struct InterData { void *channel; short position; char buffer[256]; };
-
- short DNet_DoWrite(struct InterData *data, char c)
- { data->buffer[data->position++] = c;
- if(data->position >= 256)
- { DWrite(data->channel, data->buffer, data->position); data->position = 0; }
- return(1);
- }
-
- void WriteText(void *dchan, char *buffer, short n)
- {
- struct InterData data;
- data.position = 0; data.channel = dchan;
- if(rawlocalecho && moderaw)
- { AWrite(aout, buffer, n); if(alogfile) AWrite(alogfile, buffer, n); }
- MapText(DNet_DoWrite, &data, (unsigned char *)buffer, n);
- if(data.position) DWrite(data.channel, data.buffer, data.position);
- }
-
-
-
- /**********************************************************/
- long main(int argc, char **argv)
- /**********************************************************
- Do the minimal term stuff!
- Wait on our message ports for incoming
- **********************************************************/
- {
- long amask, dmask, mask;
- char *hostname = NULL,
- inbuf[INBUFSIZE],
- currpkt, scriptmode;
-
- UWORD port = PORT_IALPHATERM;
- struct Process *us;
- startmem = AvailMem(MEMF_PUBLIC);
-
- /** STUFF WE NEED */
- out = Output(); in = Input(); err = Open("*", MODE_OLDFILE);
- us = (struct Process *)FindTask(NULL); SetSignal(0,SIGNALS);
- spf(prg, sizeof(prg), "%s [%s %ld]", argv[0], us->pr_Task.tc_Node.ln_Name, us->pr_TaskNum);
- IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0);
- GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
-
-
- /** PRINT USAGE */
- fpf(out,"ShellTerm for DNET (uc) Stone, SST\n"
- "email: c9107253@mystra.newcastle.edu.au or c9107253@cs.newcastle.edu.au\n"
- "\nCTRL-\\ or CTRL-F then CTRL-C to quit, CTRL-F for options\n\n");
- if( argc<2 )
- fpf(err,"(Use: %s [>file] [<file] [DNET_PORTNUMBER] [NETWORK])\n", argv[0]);
-
-
- /** PARSE COMMAND LINE */
- if(argc > 1) port = (UWORD) atoi(argv[1]);
- if(argc > 2) hostname = argv[2];
-
-
- /** GET ASYNC INPUT & OUTPUT HANDLES ON DIFFERENT PORTS */
- if(! (ain = AEasyMakeFD2AFD(NULL, in)))
- { fpf(err, "No input!?\n"); goto e3; }
- if(! (aout = AEasyMakeFD2AFD(NULL, out)))
- { fpf(err, "No output!?\n"); goto e3; }
- if(!IsInteractive(((long)(ain->FileHandle))>>2))
- { fpf(err, "Warning: input is not of console type\n"); conwdw = NULL; }
-
-
- /** FIND WINDOW OF THIS CONSOLE PROCESS */
- if(IsInteractive(((long)(aout->FileHandle))>>2)) {
- struct InfoData *info;
- if(!(info = (struct InfoData *)
- AllocMem(sizeof(struct InfoData), MEMF_CHIP | MEMF_CLEAR)) )
- { fpf(err, "No memory left!\n"); goto e3; }
- ASendPacket(aout, ACTION_DISK_INFO, ((long)info)>>2, 0, 0, 0);
- AResultWait(aout);
- conwdw = (struct Window *)info->id_VolumeNode;
- fpf(err, "window=%08lx COLS=%ld, ROWS=%ld\n",conwdw,
- COLUMNS(conwdw), ROWS(conwdw));
- if(((long)conwdw)&1) conwdw = NULL;
- FreeMem(info, sizeof(struct InfoData));
- } else fpf(err,"WARNING: output is not interactive\n");
- checkwindowsize = conwdw? 1:0;
-
-
- /** INITIALIZE STUFF */
- DoPacket(ain, 0, 0, currpkt = IN_WAIT);
- overridepkt = IN_NULL;
- cmds_lf();
- cmds_localechooff();
- moderaw = 0; gettingoptions = 0;
-
-
- /** DO THAT FUNKY DNET STUFF */
- fpf(out,"Opening port %ld on network %s ",port,hostname?hostname:"0");
- if( ! (chan = DOpen(hostname, port, 20, 15)) )
- { fpf(err,"Sorry, Unable to connect\n"); goto e3; }
- DQueue(chan, 32);
- /* DIoctl(chan, CIO_SETROWS, 25, 0); DIoctl(chan, CIO_SETCOLS, 80, 0); */
- fpf(out,"connected\n");
-
-
- /** KEEP ON LOOPING */
- dmask = 1 << ((PORT *)chan)->mp_SigBit;
- amask = 1 << ASIGBIT(ain);
- for (notdone = 1; notdone;) {
-
- /** CHECK THE WINDOW SIZE */
- if(conwdw && checkwindowsize) {
- if(columns != COLUMNS(conwdw))
- DIoctl(chan, CIO_SETCOLS, columns = COLUMNS(conwdw), 0);
- if(rows != ROWS(conwdw))
- DIoctl(chan, CIO_SETROWS, rows = ROWS(conwdw), 0);
- }
-
- mask = Wait(amask | dmask | SIGNALS);
-
- /** CHECK ASYNC INPUT FROM USER */
- if (mask & amask) {
- long n; struct AFileHandle *currafh;
-
- /** BE *VERY* CAREFUL ON WHERE WE MAY "ACCIDENTALLY" GETMSG */
- while(currafh = AGetReply(ain->APort)) {
- n = AResult(currafh);
- if(currafh == ain) {
- /** CHECK REPLY OF PACKET */
- switch(currpkt) {
- case IN_WAIT:
- currpkt = n? IN_CHARS: IN_WAIT;
- break;
- case IN_CHARS:
- currpkt = IN_WAIT;
- if(!n) notdone = 0;
- else if(n > 0) {
- if(gettingoptions && !moderaw) {
- inbuf[n] = '\0';
- ParseCommand(inbuf);
- gettingoptions = 0;
- } else
- WriteText(chan, inbuf, n);
- }
- break;
- case IN_RAWSET:
- currpkt = IN_WAIT;
- if(!n) fpf(err, "Couldn't set terminal mode RAW\n");
- else moderaw = 1;
- break;
- case IN_RAWCLR:
- currpkt = IN_WAIT;
- moderaw = 0;
- break;
- }
- /** SEND OUT NEXT PACKET (NOW CURRENT PACKET) */
- if(overridepkt) currpkt = overridepkt; overridepkt = 0;
- DoPacket(currafh, inbuf, sizeof(inbuf)-4, currpkt);
-
- } /* else OTHER INPUT FILES (others?? nah!) */
- }
- }
-
-
- /** CHECK SIGNALS (AND SEND THEM PERHAPS) */
- if(mask & SIGBREAKF_CTRL_C) {
- if(gettingoptions) cmds_quit();
- else { char c = 3; DWrite(chan, &c, 1); }
- }
-
- if(mask & SIGBREAKF_CTRL_D)
- { char c = 4; DWrite(chan, &c, 1); }
-
- if(mask & SIGBREAKF_CTRL_E)
- { char c = 5; DWrite(chan, &c, 1); }
-
- if(mask & SIGBREAKF_CTRL_F) {
- if(gettingoptions) {
- cmds_flush();
- gettingoptions = 0;
- } else cmds_getoptions();
- }
-
-
- /** CHECK DNET */
- if (mask & dmask) {
- long n;
- if ((n = DNRead(chan, Buf, sizeof(Buf))) > 0) {
- /* WE GOT SOME TEXT! PRINT TO STD OUTPUT! */
- AWrite(aout, Buf, n);
- if(alogfile) AWrite(alogfile, Buf, n);
- } else if (n == -2) {
- short val, cmd; char aux;
- cmd = DGetIoctl(chan, &val, &aux);
- switch(cmd) {
- case CIO_MODE:
- overridepkt = val ? IN_RAWCLR: IN_RAWSET; break;
- case CIO_SETROWS:
- break;
- case CIO_SETCOLS:
- break;
- }
-
- } else if (n < 0) cmds_quit();
- }
-
- }
-
-
- /** END ALL THE PAIN */
- e3:
- if(ain && moderaw) {
- fpf(err,"\nChanging mode back to normal");
- AResultWait(ain);
- DoPacket(ain, 0, 0, IN_RAWCLR); }
-
- fpf(err,"\n%s Closing channel. ", prg);
- if(chan) DClose(chan);
- /** CLOSE ALL FILES ON THE 2 PORTS */
- fpf(err,"output. ");
- ADeletePort(aout->APort);
- fpf(err,"input. ");
- ADeletePort(ain->APort);
- fpf(err,"done!\n");
- if(err) Close(err);
- CloseLibrary((LIB *)IntuitionBase);
- CloseLibrary((LIB *)GfxBase);
- return(0);
- }
-
- /* to add:
-
- arexx support
- text message support
-
- */
-